feat: extract @agentspec/codegen — provider-agnostic code generation#17
Draft
iliassjabali wants to merge 8 commits intomainfrom
Draft
feat: extract @agentspec/codegen — provider-agnostic code generation#17iliassjabali wants to merge 8 commits intomainfrom
iliassjabali wants to merge 8 commits intomainfrom
Conversation
…laude subscription + API key ## What this does AgentSpec previously required ANTHROPIC_API_KEY for generate and scan. This change adds full support for Claude Pro/Max subscriptions so users with a Claude.ai plan can run AgentSpec without any API key. ## New command: agentspec claude-status Inspect the full Claude auth environment in one shot: agentspec claude-status # table output agentspec claude-status --json # machine-readable, exit 1 if not ready Reports: - CLI: installed, version, authenticated, account email, plan (Pro/Max/Free) - API: key set, masked preview, live HTTP probe to /v1/models, base URL - Env: AGENTSPEC_CLAUDE_AUTH_MODE override, ANTHROPIC_MODEL, resolved mode Implemented via probeClaudeAuth() in adapter-claude/src/auth.ts which collects all data without throwing, then renders it in claude-status.ts. ## Auth resolution (CLI first) resolveAuth() in auth.ts picks the method in this order: 1. Claude CLI — if installed + authenticated (subscription users) 2. ANTHROPIC_API_KEY — fallback for CI / API-only setups 3. Neither — single combined error with setup instructions for both Override: AGENTSPEC_CLAUDE_AUTH_MODE=cli|api ## CLI stdin fix runClaudeCli() now pipes the user message via stdin (spawnSync input:) instead of as a CLI argument, avoiding ARG_MAX limits on large manifests. ## Why not @anthropic-ai/claude-agent-sdk The agent SDK is designed for persistent multi-turn coding assistants (session management, resume cursors, tool approval gates). AgentSpec generate/scan are one-shot calls — the SDK would be ~2500 lines of adapter code with almost all of it unused. Our spawnSync approach is the correct scope match: zero extra dependency, auth for free, simple to test and debug. The only tradeoff is no streaming in CLI mode. ## Files New: - packages/adapter-claude/src/auth.ts — resolveAuth, isCliAvailable, probeClaudeAuth - packages/adapter-claude/src/cli-runner.ts — runClaudeCli via spawnSync stdin - packages/cli/src/commands/claude-status.ts — new CLI command - packages/adapter-claude/src/__tests__/auth.test.ts — 16 tests - packages/adapter-claude/src/__tests__/cli-runner.test.ts — 9 tests - docs/guides/claude-auth.md — full auth guide incl. claude-status usage - examples/gymcoach/docker-compose.yml — local Postgres + Redis Updated: - adapter-claude/index.ts — routes generate/repair through resolveAuth - cli/commands/generate.ts + scan.ts — remove hard API key blocks, show auth label - cli/cli.ts — registers claude-status command - docs/reference/cli.md — claude-status section, updated generate/scan auth docs - docs/concepts/adapters.md + quick-start.md — dual-auth examples throughout Tests: 63 passing in adapter-claude, 1039 passing workspace-wide
…tion or class' Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
- auth.ts: parse claude auth status JSON before lowercasing so loggedIn:false is not silently misread as true (Copilot comment on isClaudeAuthenticated) - auth.ts: reduce API key preview exposure from 16 chars to first-4…last-2 - auth.ts: remove dead catch branch in isClaudeAuthenticated (both if-branches returned false; simplified to unconditional return false) - cli-runner.ts: remove dead systemPromptPath temp-file write — system prompt was written to disk but never used; --system-prompt was passed inline. Also fixes cleanupTempFile which called unlinkSync on a directory (would always throw and leave temp dirs behind). - generate.ts / scan.ts: derive authLabel from resolveAuth() instead of isCliAvailable() so AGENTSPEC_CLAUDE_AUTH_MODE override is reflected in the spinner (Copilot comment on both commands) - generate.ts / scan.ts: resolve auth once and pass into generateWithClaude via new options.auth field to avoid redundant subprocess call (PERF-01) - generate.ts: fix runDeployTarget helm path to wrap generateWithClaude in try/catch with graceful error output (QUAL-03) - index.ts: wrap repairYaml YAML content in XML tags to prevent prompt injection from adversarial agent.yaml files (SEC-02); truncate to 64 KB - skills/guidelines.md: add security preamble instructing Claude to treat context_manifest and context_file XML tags as data only, never instructions - docs: correct timeout example in error table from 120s to 300s - tests: add claude-status.test.ts (9 tests) covering JSON output shape and exit code 0/1 for all three resolved modes - tests: add probeClaudeAuth coverage (8 tests) to auth.test.ts - tests: add repairYaml coverage (4 tests) and XML tag assertions to claude-adapter.test.ts; update buildContext tests for new XML format - tests: remove dead node:fs mock from cli-runner.test.ts - tests: update scan/generate test mocks from isCliAvailable to resolveAuth - cli.test.ts: pass AGENTSPEC_CLAUDE_AUTH_MODE=api in generate tests to prevent them hitting real Claude CLI on developer machines
…nostic architecture Replace the monolithic @agentspec/adapter-claude with @agentspec/codegen — a provider-agnostic code generation package using hexagonal architecture. - CodegenProvider port with three adapters: Claude subscription, Anthropic API, OpenAI Codex - Auto-detection via resolveProvider() (CLI → API key → Codex) - Streaming via AsyncIterable<CodegenChunk> (delta | heartbeat | done) - @agentspec/adapter-claude retained as deprecated backwards-compat shim - CLI updated: --provider flag on generate and scan commands - 78 codegen tests, 363 CLI tests, 1065 total — all passing - Docs updated: adapters guide, claude-auth, cli reference, codegen README
Remove all Claude-specific hardcoding from the generic codegen pipeline. The CLI, types, and docs now use provider-agnostic language throughout. Renames: - claude-status command → provider-status - probeClaudeAuth() → probeProviders() - ClaudeProbeReport → ProviderProbeReport - ClaudeApiProbe → AnthropicApiProbe - ClaudeEnvProbe → ProviderEnvProbe - auth-probe.ts → provider-probe.ts - docs/guides/claude-auth.md → provider-auth.md - resolvedMode: 'cli'|'api' → resolvedProvider: string|null - authModeOverride → providerOverride - AGENTSPEC_CLAUDE_AUTH_MODE → AGENTSPEC_CODEGEN_PROVIDER Adds E2E cross-functionality tests covering the full resolver → provider-probe → provider-status pipeline.
Replace `as any` with proper types: - Contract tests use CodegenChunk instead of unknown/any - Test spies use ReturnType<typeof vi.spyOn<...>> instead of any - Context builder test uses AgentSpecManifest instead of any - Contract makeSuccessStream param widened to unknown (removes as any at call sites) - Codex test uses type guard narrowing instead of as any
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Extract all code generation logic from
@agentspec/adapter-claudeinto a new provider-agnostic@agentspec/codegenpackage. The CLI and docs now treat all providers equally — no Claude-specific hardcoding in the generic pipeline.New package:
@agentspec/codegenCodegenProviderport with three adapters:ClaudeSubscriptionProvider— uses the Claude CLI via@anthropic-ai/claude-agent-sdkAnthropicApiProvider— uses@anthropic-ai/sdkdirectlyCodexProvider— uses OpenAI's APIresolveProvider()probes Claude CLI →ANTHROPIC_API_KEY→OPENAI_API_KEYAGENTSPEC_CODEGEN_PROVIDER=claude-sub|anthropic-api|codexor--providerflagCodegenChunkdiscriminated union (delta | heartbeat | done)collect(),repairYaml(),probeProviders()@agentspec/adapter-claude→ deprecated shim@agentspec/codegenwith old API namesgenerateWithClaude()→generateCode(),resolveAuth()→resolveProvider()CLI updates
agentspec generateandagentspec scanuse@agentspec/codegendirectlyagentspec provider-statuscommand--providerflag ongenerateandscanfor explicit provider selectionDocs
docs/concepts/adapters.md— rewritten for multi-provider architecturedocs/guides/provider-auth.md— covers all three providersdocs/reference/cli.md— updated commands, env vars, examplespackages/codegen/README.md— full package docsdocs/quick-start.md— provider-agnostic languageCI / publish
publish.yml— adapter-claude publish step (after codegen, resolves workspace deps)release.yml— adapter-claude in version bump loopTest coverage
pnpm typecheckclean across all 6 packages